package com.levi.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.retry.annotation.Retryable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.levi.annotation.Login;
import com.levi.constants.Constants;
import com.levi.domain.User;
import com.levi.holder.ThreadLocalHodler;
import com.levi.service.CommonService;
import com.levi.service.UserService;
import com.levi.threadpool.ThreadPoolExecutorMdcWrapper;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shentong
 * @since 2022/3/8 9:56 PM
 */
@Slf4j
@RestController
public class CommonController {

  private final ThreadLocal<Integer> localNum = ThreadLocal.withInitial(() -> 10);

  private Integer num = 10;

  @Autowired
  private CommonService commonService;

  @Autowired
  private UserService userService;

  @Autowired
  private ThreadPoolExecutorMdcWrapper threadPoolExecutorMdcWrapper;

  @Autowired
  private RestTemplate restTemplate;

  @GetMapping("/test/getAll")
  @Login
  public String getAll() {
    log.info("commonService:{}", commonService.getClass());
    return "getAll";
  }

  @GetMapping("/test/getHeader")
  public String getHeader() {
    return "getHeader";
  }

  @GetMapping("getIp")
  public String getIp() {
    log.info("getIp");
    threadPoolExecutorMdcWrapper.execute(() -> {
      log.info("子线程  getIp");
    });
    restTemplate.getForObject("http://localhost:8080/testHttp", String.class);
    return "getIp";
  }

  @GetMapping("/testHttp")
  public String testHttp(ServletServerHttpRequest request) {
    String traceId = request.getHeaders().getFirst(Constants.TRACE_ID);
    log.info("http traceId");
    return traceId;
  }

  @GetMapping("/test/filter")
  public String testFilter() {
    return "testFilter!!";
  }

  /**
   * 使用ThreadLocal解决线程安全问题
   *
   * @return
   */
  @GetMapping("/getLocalNum")
  public Integer getLocalNum() {
    Integer num = localNum.get();
    num++;
    log.info("num:===>{}", num);
    return num;
  }

  /**
   * num是线程共享变量，线程不安全
   *
   * @return
   */
  @GetMapping("/getNum")
  public Integer getNum() {
    num++;
    log.info("num:====>{}", num);
    return num;
  }

  @GetMapping("/testThreadLocalHolder")
  public void testThreadLocalHolder() {
    User user = new User();
    user.setName("张三");
    user.setAge(1);
    ThreadLocalHodler.holder.set(user);
    commonService.testThreadLocalHolder();
    userService.TestThreadLocalHolder();
  }

  @GetMapping("reRetry")
  @Retryable
  public void reRetry() {
    log.info("执行了reRetry方法");
    throw new RuntimeException("error");
  }

  @GetMapping("/testValueParam")
  public String testValueParam(@Value("${param.test}") String param) {
    return param;
  }

  @GetMapping("decreStock")
  public void decreStock() {
    commonService.decreStock();
  }

  @GetMapping("/sendSms")
  public void sendSms() {
    log.info("开始发送短信");
    commonService.sendSms();
  }
}
